#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Filename: case_batch_import.py
# Author: ChenChangSong
# Date: 2025-08-24

"""
功能描述: 批量导入测试用例到TAPD(每次最多200条)
https://open.tapd.cn/document/api-doc/API%E6%96%87%E6%A1%A3/api_reference/tcase/batch_add_tcase.html
"""

import sys
import os
import time
from comm.common_code import *
def tcases_batch_save(all_case_list, max_retries=5):
    """批量导入测试用例到TAPD(每次最多200条)
    
    Args:
        all_case_list: 用例列表，格式如下:
            [{
                "access_token": excel_data['access_token'],
                "workspace_id": "项目ID",  # 必填
                "category_id": "目录ID",   # 可选
                "name": "用例名称",        # 必填
                "precondition": "前置条件", # 可选
                "steps": "用例步骤",       # 可选
                "expectation": "预期结果",  # 可选
                "creator": "创建人"        # 可选
            }, ...]
        max_retries: 最大重试次数，默认5次
        
    Returns:
        tuple: (成功用例列表, 失败用例列表)
    """
    if not all_case_list:
        logger.warning("用例列表为空，无需导入")
        return {'status': 1, 'data': []}, []
    
    # 初始化成功和失败的用例
    all_success_cases = {'status': 1, 'data': []}
    failed_cases = all_case_list.copy()
    retry_count = 0
    
    while retry_count < max_retries and failed_cases:
        logger.info(f'第 {retry_count + 1} 次尝试导入，剩余 {len(failed_cases)} 条用例')
        
        # 发送批量导入请求
        url = "https://api.tapd.cn/tcases/batch_save"
        response_code, response = api_request(
            method="POST", 
            url=url, 
            headers=headers_json, 
            json=failed_cases
        )
        
        # 检查响应是否有效
        if response_code != 200:
            logger.error(f'请求失败，HTTP状态码: {response_code}')
            retry_count += 1
            time.sleep(random.uniform(2, 5))
            continue
            
        if not response or response.get('status') != 1:
            logger.error(f'TAPD API返回错误: {response.get("info", "未知错误") if response else "无响应"}')
            retry_count += 1
            time.sleep(random.uniform(2, 5))
            continue
        
        # 检查响应数据格式
        if 'data' not in response or not isinstance(response['data'], list):
            logger.error('响应格式错误: data字段缺失或不是列表')
            retry_count += 1
            time.sleep(random.uniform(2, 5))
            continue
        
        # 验证响应数据长度与请求数据长度一致
        if len(response['data']) != len(failed_cases):
            logger.error(f'响应数据长度({len(response["data"])})与请求用例数量({len(failed_cases)})不一致')
            retry_count += 1
            time.sleep(random.uniform(2, 5))
            continue
        
        logger.info(f"收到响应数据: {len(response['data'])} 条记录")
        
        # 处理每个响应项
        success_cases = []
        new_failed_cases = []
        
        for i, item in enumerate(response['data']):
            original_case = failed_cases[i]
            
            # 检查响应项格式
            if isinstance(item, dict) and 'Tcase' in item and isinstance(item['Tcase'], dict):
                tcase = item['Tcase']
                
                # 验证必要字段存在
                if tcase.get('id') and tcase.get('name'):
                    # 只保留需要的字段
                    filtered_tcase = {
                        'id': tcase.get('id'),
                        'name': tcase.get('name'),
                        'category_id': tcase.get('category_id')
                    }
                    success_cases.append({'Tcase': filtered_tcase})
                    logger.debug(f"用例 '{original_case['name']}' 导入成功, ID: {tcase.get('id')}")
                else:
                    logger.warning(f"用例 '{original_case['name']}' 响应数据不完整: {tcase}")
                    new_failed_cases.append(original_case)
            else:
                logger.warning(f"用例 '{original_case['name']}' 导入失败，响应格式错误: {item}")
                new_failed_cases.append(original_case)
        
        # 更新成功和失败列表
        all_success_cases['data'].extend(success_cases)
        failed_cases = new_failed_cases
        
        logger.info(f'本次成功导入 {len(success_cases)} 条用例，失败 {len(failed_cases)} 条')
        
        # 如果还有失败用例，等待后重试
        if failed_cases:
            retry_count += 1
            if retry_count < max_retries:
                wait_time = random.uniform(2, 5)
                logger.info(f'等待 {wait_time:.2f} 秒后进行第 {retry_count + 1} 次重试')
                time.sleep(wait_time)
        else:
            break  # 所有用例都成功，退出循环
    
    # 设置最终状态
    if not all_success_cases['data']:
        all_success_cases['status'] = 0
    
    logger.info(f'批量导入完成: 成功 {len(all_success_cases["data"])} 条，失败 {len(failed_cases)} 条')
    
    if failed_cases:
        failed_names = [case.get('name', '未知用例') for case in failed_cases]
        logger.error(f'最终失败的用例: {failed_names}')
        log_to_ui_error(f'最终失败的用例: {failed_names}')
    
    return all_success_cases, failed_cases

if __name__ == "__main__":
    category_id ='1166606973001016098'
    excel_data = get_excel_data()
    all_case_list=[
        {
        "access_token": excel_data['access_token'],
        "workspace_id": excel_data['项目ID'], # 项目ID(必填)
        "category_id": category_id,         # 用例目录ID
        "name": "简单用例819",                   # 用例名称(必填)
        "precondition": "前置条件1",            # 前置条件
        "steps": "用例步骤2",                   # 用例步骤
        "expectation": "预期结果3",             # 预期结果
        "creator": excel_data['创建人'],       # 创建人
        },
        {
        "access_token": excel_data['access_token'],
        "workspace_id": excel_data['项目ID'], # 项目ID(必填)
        "category_id": category_id,         # 用例目录ID
        "name": "简单用例820",                   # 用例名称(必填)
        "precondition": "前置条件1",            # 前置条件
        "steps": "用例步骤2",                   # 用例步骤
        "expectation": "预期结果3",             # 预期结果
        "creator": excel_data['创建人'],       # 创建人
        }
    ]
    success_response, failed_cases = tcases_batch_save(all_case_list)